#ifndef MBRSYNTH_H
#define MBRSYNTH_H

#include <string.h>
#include <fstream>
#include <iostream>
#include <sstream>

#include <sekai/EventList.h>
#include <sekai/ControlTrack.h>
#include <sekai/VoiceSampler.h>
#include <sekai/SynthInterface.h>

#define IMPULSE_RESPONSE_MAX 2048

enum synthType
{
    FVOX=0,
    UTAU=1,
    MBROLA=2,
    ESPEAK=3
};

struct MBRConfig
{
    synthType type;
    int mbr_period;
    float frame_period;
    int fft_size;
};

class MBRSynth : public IUnisyn, public VoiceSampler {
  int _samplerate = 0;
  std::map<std::string, VoiceDef *> _voicemap;
  EventList<PhoEvent> _phoEvents;
  float *_impulseResponse;
  ControlTrack *_ctrl = nullptr;
  std::string _basedir;
  MBRConfig* _config = nullptr;
  FILE* _debugfile = nullptr;
  float _maxvol=0;

  void getImpulseResponse(float currentTime, PhoEvent *event,
                          float *impulseResponse, int *impulseResponseLength,
                          float morph);
  
  void load(const std::string &unit);

 public:
  virtual void addUnit(const std::string &basename, int, float *, float *);
  virtual void setBasedir(const std::string &basedir) { _basedir= basedir; }
  virtual bool saveWave(const std::string &filename);
  virtual void setConfig(MBRConfig* config){_config=config;}
  
 protected:

  virtual bool addOnePulse();
  virtual float getLengthForUnit(const std::string &fileName);
  virtual std::string getPhoLine(const std::string &fileName,int index);
  virtual void postProcess(float* data, int size);

 public:
  MBRSynth(ControlTrack *ctrl, int buffer_size = IMPULSE_RESPONSE_MAX * 4);
  int samplerate() { return _samplerate; }
  void fix();
};

#endif
